'use strict';

const { getConfig } = require('uni-config-center');
const crypto = require('crypto');

/**
 * 微信商家转账功能（新版本 2025年1月15日升级后）
 * 文档：https://pay.weixin.qq.com/doc/v3/merchant/4012711988
 *
 * 新版本流程：
 * 1. 后端生成加密的package
 * 2. 前端调用wx.requestMerchantTransfer()
 * 3. 用户在微信官方页面确认
 * 4. 微信异步通知后端结果
 */

// ============ 辅助函数 ============

/**
 * 读取并处理微信支付配置
 */
function getWechatConfig() {
  let wxpayConfig;
  try {
    wxpayConfig = getConfig('wxpay-config');
  } catch (e) {
    wxpayConfig = {};
  }
  const { mchid, appid, privateKey, serial_no, apiKeyV3 } = wxpayConfig;

  if (!mchid || !appid || !privateKey || !serial_no || !apiKeyV3) {
    throw new Error('微信支付配置不完整，请检查 uni-config-center/wxpay-config/config.json');
  }

  return { mchid, appid, privateKey, serial_no, apiKeyV3 };
}

/**
 * 处理私钥中的换行符
 */
function processPrivateKey(privateKey) {
  let processedPrivateKey = privateKey;
  if (typeof privateKey === 'string') {
    const hasRealNewline = privateKey.includes('\n');
    const hasEscapedNewline = privateKey.includes('\\n');

    if (!hasRealNewline && hasEscapedNewline) {
      processedPrivateKey = privateKey.replace(/\\n/g, '\n');
      console.log('[微信支付] 已将 \\\\n 替换为真正的换行符');
    }
  }

  // 验证私钥格式
  if (!processedPrivateKey.includes('BEGIN PRIVATE KEY') || !processedPrivateKey.includes('END PRIVATE KEY')) {
    throw new Error('私钥格式错误：缺少 BEGIN/END PRIVATE KEY 标识');
  }

  return processedPrivateKey;
}

/**
 * 生成签名
 */
function generateSignature(signatureStr, privateKey) {
  const sign = crypto.createSign('RSA-SHA256');
  sign.update(signatureStr);
  return sign.sign(privateKey, 'base64');
}

/**
 * 生成加密的package
 * 新版本流程中，后端生成package，前端调用wx.requestMerchantTransfer()
 *
 * 注意：已升级到新版本 API（2025年1月15日）
 * 旧版本 API: /v3/transfer/batches（已停用）
 * 新版本 API: /v3/transfer/direct-transfer（推荐）
 */
async function generateTransferPackage(params) {
  const debugInfo = {
    step: '',
    config: {},
    privateKeyInfo: {},
    packageInfo: {}
  };

  try {
    debugInfo.step = '1. 读取配置';
    const { mchid, appid, privateKey, serial_no, apiKeyV3 } = getWechatConfig();

    debugInfo.config = {
      mchid: mchid,
      appid: appid,
      serial_no: serial_no,
      privateKeyLength: privateKey ? privateKey.length : 0
    };

    debugInfo.step = '2. 处理私钥';
    const processedPrivateKey = processPrivateKey(privateKey);

    debugInfo.step = '3. 生成转账订单号';
    // 生成唯一的转账号（只能包含数字和字母，不能包含下划线）
    const transferTimestamp = Date.now().toString();
    const randomStr = Math.random().toString(36).substring(2, 11);
    const outBillNo = `transfer${transferTimestamp}${randomStr}`;
    console.log('[微信支付] 生成商户单号:', outBillNo);

    debugInfo.step = '4. 准备转账参数（新版本API）';
    // 构建回调URL（微信要求不能携带参数）
    const notifyUrl = 'https://fc-mp-0aca9d9a-5e35-450b-970f-895109088651.next.bspapp.com/http/user-center';

    // 新版本 API 参数结构（根据官方文档）
    const transferParams = {
      appid: appid,
      out_bill_no: outBillNo,  // 新版本：商户单号（必填）
      transfer_scene_id: '1000',  // 现金营销场景（必填）
      openid: params.openid,  // 收款用户的openid（必填）
      transfer_amount: params.amount,  // 转账金额（单位：分，必填）
      transfer_remark: '佣金提现',  // 转账备注（必填）
      notify_url: notifyUrl,  // 异步通知URL（选填）
      // 转账场景报备信息（必填）
      transfer_scene_report_infos: [
        {
          info_type: '活动名称',
          info_content: '佣金提现'
        },
        {
          info_type: '奖励说明',
          info_content: '用户佣金提现'
        }
      ]
    };

    debugInfo.packageInfo.notifyUrl = notifyUrl;
    console.log('[微信支付] 异步通知URL:', notifyUrl);

    debugInfo.packageInfo.transferParams = transferParams;
    console.log('[微信支付] 转账参数（新版本API）:', JSON.stringify(transferParams, null, 2));

    debugInfo.step = '5. 生成签名';
    const timestamp = Math.floor(Date.now() / 1000);
    const nonce = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
    // 新版本 API 端点（2025年1月15日升级后）
    const apiPath = '/v3/fund-app/mch-transfer/transfer-bills';
    const bodyStr = JSON.stringify(transferParams);
    const signatureStr = `POST\n${apiPath}\n${timestamp}\n${nonce}\n${bodyStr}\n`;

    const signature = generateSignature(signatureStr, processedPrivateKey);

    debugInfo.packageInfo.signature = {
      timestamp: timestamp,
      nonce: nonce,
      signatureLength: signature.length,
      signaturePreview: signature.substring(0, 50) + '...'
    };

    console.log('[微信支付] 签名生成成功，长度:', signature.length);

    debugInfo.step = '6. 调用微信发起转账API（新版本）';
    // 调用微信的"发起转账"API，获取package_info
    // 使用 uniCloud.httpProxyForEip 确保使用固定出口IP
    const fullUrl = `https://api.mch.weixin.qq.com${apiPath}`;

    const authHeader = `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",nonce_str="${nonce}",timestamp="${timestamp}",serial_no="${serial_no}",signature="${signature}"`;

    console.log('[微信支付] 调用微信API（新版本）:', fullUrl);
    console.log('[微信支付] API端点:', apiPath);
    console.log('[微信支付] Authorization:', authHeader.substring(0, 50) + '...');
    console.log('[微信支付] 使用固定出口IP代理发送请求...');

    let apiResult;
    try {
      // 使用 uniCloud.httpProxyForEip 发送请求，确保使用固定出口IP
      console.log('[微信支付] 开始调用 uniCloud.httpProxyForEip.postJson...');
      const result = await uniCloud.httpProxyForEip.postJson(
        fullUrl,
        transferParams,  // 直接传递对象，不需要JSON.stringify
        {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': authHeader,
          'Wechatpay-Serial': serial_no
        }
      );

      console.log('[微信支付] 收到响应，响应对象类型:', typeof result);
      console.log('[微信支付] 响应对象完整内容:', JSON.stringify(result, null, 2));

      // 检查响应是否存在
      if (!result) {
        throw new Error('微信API返回空响应');
      }

      // uniCloud.httpProxyForEip 返回的格式是 { headers, body, statusCode, statusCodeValue }
      const statusCode = result.statusCodeValue || result.statusCode;
      const responseBody = result.body;

      console.log('[微信支付] API响应状态码:', statusCode);
      console.log('[微信支付] API响应数据:', JSON.stringify(responseBody, null, 2));

      // 检查响应状态
      if (statusCode !== 200) {
        // 更详细的错误信息提取
        let errorMsg = '未知错误';
        if (responseBody) {
          if (typeof responseBody === 'string') {
            errorMsg = responseBody;
          } else if (responseBody.message) {
            errorMsg = responseBody.message;
          } else if (responseBody.msg) {
            errorMsg = responseBody.msg;
          } else if (responseBody.error_description) {
            errorMsg = responseBody.error_description;
          } else {
            errorMsg = JSON.stringify(responseBody);
          }
        }
        console.error('[微信支付] 微信API错误详情:', {
          statusCode: statusCode,
          body: responseBody,
          errorMsg: errorMsg
        });
        throw new Error(`微信API返回错误: ${statusCode} - ${errorMsg}`);
      }

      apiResult = responseBody;
    } catch (e) {
      console.error('[微信支付] 调用微信API失败:', e.message);
      console.error('[微信支付] 错误堆栈:', e.stack);
      throw new Error(`生成package失败: ${e.message}`);
    }

    if (!apiResult || !apiResult.package_info) {
      throw new Error('微信API未返回package_info');
    }

    debugInfo.packageInfo.apiResponse = {
      out_bill_no: apiResult.out_bill_no,
      package_info: apiResult.package_info.substring(0, 50) + '...'
    };

    debugInfo.step = '7. 返回package';
    const result = {
      mchId: mchid,
      appId: appid,
      package: apiResult.package_info,
      outBillNo: apiResult.out_bill_no  // 新版本：返回商户单号
    };

    debugInfo.packageInfo.result = {
      mchId: mchid,
      appId: appid,
      outBillNo: apiResult.out_bill_no,
      packageLength: apiResult.package_info.length
    };

    console.log('[微信支付] Package生成成功（新版本API）');
    console.log('[微信支付] 调试信息:', JSON.stringify(debugInfo, null, 2));

    return result;

  } catch (error) {
    console.error('[微信支付] 生成package失败:', error);
    console.error('[微信支付] 调试信息:', JSON.stringify(debugInfo, null, 2));

    const enhancedError = new Error(error.message + '\n\n=== 调试信息 ===\n' + JSON.stringify(debugInfo, null, 2));
    enhancedError.debugInfo = debugInfo;
    throw enhancedError;
  }
}

/**
 * 旧版本：直接调用微信API（已弃用，保留用于兼容）
 */
async function transferToBalance(params) {

  // 用于收集调试信息，将返回到前端
  const debugInfo = {
    step: '',
    config: {},
    privateKeyInfo: {},
    signatureInfo: {},
    authInfo: {},
    requestInfo: {},
    responseInfo: {}
  };

  try {
    debugInfo.step = '1. 读取配置';
    const { mchid, appid, privateKey, serial_no } = getWechatConfig();

    debugInfo.step = '2. 处理私钥';
    const processedPrivateKey = processPrivateKey(privateKey);

    // 验证证书序列号格式
    if (!serial_no || serial_no.length < 10) {
      throw new Error('证书序列号格式错误');
    }

    debugInfo.step = '3. 构建请求体';

    const url = '/v3/transfer/batches';
    const fullUrl = `https://api.mch.weixin.qq.com${url}`;

    const body = {
      appid: appid,
      out_batch_no: `transfer_${Date.now()}`,
      batch_name: '用户佣金提现',
      batch_remark: '佣金提现',
      total_amount: params.amount,
      total_num: 1,
      transfer_scene_id: '1000',  // 【小程序载体】转账场景ID，1000=现金营销
      transfer_detail_list: [{
        out_detail_no: `detail_${Date.now()}`,
        transfer_amount: params.amount,
        transfer_remark: '佣金提现',
        openid: params.openid
      }]
    };

    const bodyStr = JSON.stringify(body);
    debugInfo.requestInfo.body = body;
    debugInfo.requestInfo.bodyStr = bodyStr;
    console.log('[微信支付] 请求体:', bodyStr);

    debugInfo.step = '4. 生成签名';
    // 生成签名
    const timestamp = Math.floor(Date.now() / 1000);
    const nonce = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);

    // 构建签名串（注意：每个部分后面都有换行符）
    const signatureStr = `POST\n${url}\n${timestamp}\n${nonce}\n${bodyStr}\n`;

    debugInfo.signatureInfo = {
      method: 'POST',
      url: url,
      timestamp: timestamp,
      nonce: nonce,
      bodyLength: bodyStr.length,
      signatureStr: signatureStr,
      signatureStrLines: signatureStr.split('\n'),
      signatureStrLineCount: signatureStr.split('\n').length
    };

    console.log('[微信支付] 签名串:', signatureStr);
    console.log('[微信支付] 签名串行数:', debugInfo.signatureInfo.signatureStrLineCount);
    console.log('[微信支付] 签名串每行内容:', debugInfo.signatureInfo.signatureStrLines);
    console.log('[微信支付] 签名串详细信息:', debugInfo.signatureInfo);

    // 使用私钥签名（使用处理后的私钥）
    const sign = crypto.createSign('RSA-SHA256');
    sign.update(signatureStr);
    const signature = sign.sign(processedPrivateKey, 'base64');

    debugInfo.signatureInfo.signature = signature;
    debugInfo.signatureInfo.signatureLength = signature.length;

    console.log('[微信支付] 签名结果:', signature);
    console.log('[微信支付] 签名结果长度:', signature.length);
    console.log('[微信支付] 签名结果字符分析:', {
      hasPlus: signature.includes('+'),
      hasSlash: signature.includes('/'),
      hasEqual: signature.includes('='),
      lastChars: signature.substring(signature.length - 10)
    });

    debugInfo.step = '5. 构建 Authorization 头';
    // 构建 Authorization 头
    // 官方文档示例：WECHATPAY2-SHA256-RSA2048 mchid="123456789",nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242",signature="...==",timestamp="1554208460",serial_no="1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C"
    const authParts = [
      `mchid="${mchid}"`,
      `nonce_str="${nonce}"`,
      `signature="${signature}"`,
      `timestamp="${timestamp}"`,
      `serial_no="${serial_no}"`
    ];
    const authorization = `WECHATPAY2-SHA256-RSA2048 ${authParts.join(',')}`;

    debugInfo.authInfo = {
      algorithm: 'WECHATPAY2-SHA256-RSA2048',
      mchid: mchid,
      nonce_str: nonce,
      timestamp: timestamp,
      serial_no: serial_no,
      signature: signature.substring(0, 50) + '...',
      signatureLength: signature.length,
      fullAuth: authorization
    };

    console.log('[微信支付] Authorization:', authorization);

    debugInfo.step = '6. 发送请求';
    const res = await uniCloud.request({
      method: 'POST',
      url: fullUrl,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'User-Agent': 'uniCloud-wxpay/1.0.0',
        'Authorization': authorization
      },
      data: body,
      dataType: 'json'
    });

    debugInfo.responseInfo = {
      statusCode: res.statusCode,
      data: res.data,
      headers: res.headers
    };

    console.log('[微信支付] 响应状态码:', res.statusCode);
    console.log('[微信支付] 响应数据:', res.data);

    if (res.statusCode !== 200 && res.statusCode !== 204) {
        console.error('[微信支付] API错误:', res.data);
        debugInfo.step = '7. 请求失败';
        const error = new Error(`微信支付API请求失败: ${res.data.message || '未知错误'}`);
        error.debugInfo = debugInfo;
        throw error;
    }

    debugInfo.step = '8. 请求成功';
    return res.data;

  } catch (error) {
    // 捕获所有错误，并附加调试信息
    console.error('[微信支付] 发生错误:', error);
    console.error('[微信支付] 调试信息:', JSON.stringify(debugInfo, null, 2));

    // 将调试信息附加到错误对象
    if (!error.debugInfo) {
      error.debugInfo = debugInfo;
    }

    // 重新抛出错误，但包含调试信息
    const enhancedError = new Error(error.message + '\n\n=== 调试信息 ===\n' + JSON.stringify(debugInfo, null, 2));
    enhancedError.originalError = error;
    enhancedError.debugInfo = debugInfo;
    throw enhancedError;
  }
}

/**
 * 解密微信异步通知中的加密数据
 * 微信使用AES-256-GCM算法加密，需要使用APIv3密钥解密
 */
function decryptWechatNotification(nonce, associatedData, ciphertext, apiKeyV3) {
  try {
    console.log('[微信支付] 开始解密通知数据...');

    // 将base64编码的密文转换为Buffer
    const ciphertextBuffer = Buffer.from(ciphertext, 'base64');

    // APIv3密钥是32字节的字符串，需要转换为Buffer
    const keyBuffer = Buffer.from(apiKeyV3, 'utf8');

    // nonce和associatedData也需要转换为Buffer
    const nonceBuffer = Buffer.from(nonce, 'utf8');
    const associatedDataBuffer = Buffer.from(associatedData, 'utf8');

    // 使用AES-256-GCM解密
    // GCM模式下，最后16字节是认证标签
    const authTag = ciphertextBuffer.slice(-16);
    const encryptedData = ciphertextBuffer.slice(0, -16);

    const decipher = crypto.createDecipheriv('aes-256-gcm', keyBuffer, nonceBuffer);
    decipher.setAAD(associatedDataBuffer);
    decipher.setAuthTag(authTag);

    let plaintext = decipher.update(encryptedData, 'binary', 'utf8');
    plaintext += decipher.final('utf8');

    console.log('[微信支付] 解密成功');
    return JSON.parse(plaintext);

  } catch (error) {
    console.error('[微信支付] 解密失败:', error);
    throw new Error(`解密通知数据失败: ${error.message}`);
  }
}

/**
 * 验证微信异步通知的签名
 * 微信会发送POST请求到你的服务器，需要验证签名确保数据来自微信
 */
function verifyWechatNotification(timestamp, nonce, body, signature, serialNo) {
  try {
    console.log('[微信支付] 验证通知签名...');

    // 构建签名串
    const signatureStr = `${timestamp}\n${nonce}\n${body}\n`;

    console.log('[微信支付] 签名串:', signatureStr);
    console.log('[微信支付] 收到的签名:', signature);
    console.log('[微信支付] 证书序列号:', serialNo);

    // 注意：实际验证需要使用微信提供的公钥
    // 这里返回true作为示例，实际应该进行真正的验证
    // TODO: 从微信API获取公钥并验证签名

    return true;
  } catch (error) {
    console.error('[微信支付] 验证签名失败:', error);
    return false;
  }
}

/**
 * 处理微信异步通知
 * 微信会在转账完成后发送异步通知
 *
 * 通知数据结构：
 * {
 *   id: "EV5XvJmrU23879148FHsdfA",
 *   create_time: "2015-05-20T13:29:35+08:00",
 *   event_type: "TRANSFER.SUCCESS",
 *   resource_type: "encrypt_resource",
 *   resource: {
 *     original_type: "transfer",
 *     algorithm: "AEAD_AES_256_GCM",
 *     ciphertext: "...",
 *     associated_data: "transfer",
 *     nonce: "..."
 *   }
 * }
 */
async function handleTransferNotification(notificationData) {
  const debugInfo = {
    step: '',
    notificationData: {}
  };

  try {
    debugInfo.step = '1. 解析通知数据';
    console.log('[微信支付] 收到异步通知:', JSON.stringify(notificationData, null, 2));

    // 通知数据结构
    const {
      id,
      create_time,
      event_type,
      resource_type,
      resource
    } = notificationData;

    debugInfo.notificationData = {
      id,
      create_time,
      event_type,
      resource_type
    };

    // 验证事件类型
    if (event_type !== 'TRANSFER.SUCCESS' && event_type !== 'TRANSFER.FAILED') {
      console.log('[微信支付] 忽略非转账事件:', event_type);
      return {
        code: 0,
        message: '事件类型不是转账事件，已忽略'
      };
    }

    debugInfo.step = '2. 验证签名';
    // 验证通知签名（这里简化处理，实际需要真正验证）
    // const isValid = verifyWechatNotification(
    //   notificationData.timestamp,
    //   notificationData.nonce,
    //   JSON.stringify(resource),
    //   notificationData.signature,
    //   notificationData.serial_no
    // );
    // if (!isValid) {
    //   throw new Error('通知签名验证失败');
    // }

    debugInfo.step = '3. 解密通知数据';
    // 使用APIv3密钥解密resource中的数据
    const { apiKeyV3 } = getWechatConfig();

    let transferData;
    if (resource.algorithm === 'AEAD_AES_256_GCM') {
      // 解密加密的资源数据
      transferData = decryptWechatNotification(
        resource.nonce,
        resource.associated_data,
        resource.ciphertext,
        apiKeyV3
      );
      console.log('[微信支付] 解密后的转账数据:', JSON.stringify(transferData, null, 2));
    } else {
      // 如果不是加密数据，直接使用
      transferData = resource;
    }

    debugInfo.step = '4. 查找提现记录（新版本API）';
    const db = uniCloud.database();

    // 新版本 API 使用 out_bill_no，旧版本使用 out_batch_no
    // 为了兼容，同时查询两个字段
    const outBillNo = transferData.out_bill_no || transferData.out_batch_no;

    console.log('[微信支付] 查询商户单号:', outBillNo);

    const withdrawalQuery = await db.collection('withdrawals')
      .where(db.command.or([
        { out_bill_no: outBillNo },
        { out_batch_no: outBillNo }
      ]))
      .get();

    if (!withdrawalQuery.data || withdrawalQuery.data.length === 0) {
      console.warn('[微信支付] 找不到对应的提现记录:', outTransferNo);
      return {
        code: 0,
        message: '找不到对应的提现记录'
      };
    }

    const withdrawal = withdrawalQuery.data[0];
    console.log('[微信支付] 找到提现记录:', withdrawal._id);

    debugInfo.step = '5. 更新提现记录（新版本API）';
    const dbCmd = db.command;

    if (event_type === 'TRANSFER.SUCCESS') {
      // 转账成功
      console.log('[微信支付] 转账成功，更新提现记录...');
      await db.collection('withdrawals').doc(withdrawal._id).update({
        status: 'success',
        transaction_id: transferData.transfer_id || transferData.batch_id,  // 新版本使用 transfer_id
        finish_time: Date.now(),
        notification_received: true,
        notification_time: Date.now()
      });
      console.log('[微信支付] 提现记录已更新为成功');
    } else if (event_type === 'TRANSFER.FAILED') {
      // 转账失败，需要回滚用户余额
      console.log('[微信支付] 转账失败，回滚用户余额...');

      await db.collection('withdrawals').doc(withdrawal._id).update({
        status: 'failed',
        error_message: transferData.fail_reason || '转账失败',
        finish_time: Date.now(),
        notification_received: true,
        notification_time: Date.now()
      });

      // 回滚用户余额
      await db.collection('users').doc(withdrawal.user_id).update({
        commission_available: dbCmd.inc(withdrawal.amount)
      });
      console.log('[微信支付] 已回滚用户余额:', withdrawal.amount);
    }

    debugInfo.step = '6. 返回成功响应';
    return {
      code: 0,
      message: '通知处理成功'
    };

  } catch (error) {
    console.error('[微信支付] 处理通知失败:', error);
    console.error('[微信支付] 调试信息:', JSON.stringify(debugInfo, null, 2));

    // 返回错误，微信会重试
    return {
      code: 500,
      message: `处理通知失败: ${error.message}`
    };
  }
}

module.exports = {
    generateTransferPackage,
    transferToBalance,
    handleTransferNotification,
    verifyWechatNotification,
    decryptWechatNotification
};
